package com.gonsin.gmessage.logic.proxy;

import com.gonsin.gmessage.annotations.GMessageEnvironment;
import com.gonsin.gmessage.logic.GMessage;
import com.gonsin.gmessage.logic.GMessageScan;
import com.gonsin.gmessage.logic.exceptions.GMessageException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanMetadataAttribute;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.*;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.annotation.AnnotationConstants;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.config.ExpressionFactoryBean;
import org.springframework.integration.config.IntegrationConfigUtils;
import org.springframework.integration.config.MessagingGatewayRegistrar;
import org.springframework.integration.gateway.GatewayMethodMetadata;
import org.springframework.integration.gateway.GatewayProxyFactoryBean;
import org.springframework.integration.util.MessagingAnnotationUtils;
import org.springframework.util.*;

import java.beans.Introspector;
import java.util.*;


/**
 * 通过BeanFactory 实例化被@GMessage批注的接口
 */
@Slf4j
public class GMessageRegister implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {


        if (importingClassMetadata.isAnnotated(GMessage.class.getName())) {

            Assert.isTrue(importingClassMetadata.isInterface(), "@GMessage 只能用在interface上");
            List<MultiValueMap<String, Object>> valuesHierarchy = captureMetaAnnotationValues(importingClassMetadata);
            Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(GMessage.class.getName());
            replaceEmptyOverrides(valuesHierarchy, annotationAttributes); // NOSONAR never null
            annotationAttributes.put("serviceInterface", importingClassMetadata.getClassName());

            if(GMessageEnvironment.LOG){
                log.info("GMessageRegister 开始注册必要的Sender接口 {} ", importingClassMetadata.getClassName());
            }
            if(GMessageEnvironment.LOG){
                log.info("GMessageRegister 使用注册器： {} ", registry);
            }
            BeanDefinitionReaderUtils.registerBeanDefinition(this.parse(annotationAttributes), registry);



//            List<MultiValueMap<String, Object>> valuesHierarchy = captureMetaAnnotationValues(importingClassMetadata);
//            Map<String, Object> annotationAttributes =
//                    importingClassMetadata.getAnnotationAttributes(GMessage.class.getName());
//            replaceEmptyOverrides(valuesHierarchy, annotationAttributes); // NOSONAR never null
//            annotationAttributes.put("serviceInterface", importingClassMetadata.getClassName());
//
//            BeanDefinition beanDefinition = new GenericBeanDefinition();
//            beanDefinition.setBeanClassName(GMessageProxyFactoryBean.class.getName());
////            MutablePropertyValues values = beanDefinition.getPropertyValues();
//
//            String serviceInterface = (String) annotationAttributes.get("serviceInterface");
//            if (!StringUtils.hasText(serviceInterface)) {
//                serviceInterface = "org.springframework.integration.gateway.RequestReplyExchanger";
//            }
//            String id = (String) annotationAttributes.get("name");
//            if (!StringUtils.hasText(id)) {
//                id = Introspector.decapitalize(serviceInterface.substring(serviceInterface.lastIndexOf(".") + 1));
//            }
//
////            values.addPropertyValue("id", id);
////            values.addPropertyValue("name", "ZhangSan");
//            //这里注册bean
//            registry.registerBeanDefinition(id, beanDefinition);

        }

    }


    public BeanDefinitionHolder parse(Map<String, Object> gatewayAttributes) {

        BeanDefinitionBuilder gatewayProxyBuilder =
                BeanDefinitionBuilder.genericBeanDefinition(GMessageProxyFactoryBean.class);


        String serviceInterface = (String) gatewayAttributes.get("serviceInterface");
        if (!StringUtils.hasText(serviceInterface)) {
            serviceInterface = "org.springframework.integration.gateway.RequestReplyExchanger";
        }
        String id = (String) gatewayAttributes.get("name");
        if (!StringUtils.hasText(id)) {
            id = Introspector.decapitalize(serviceInterface.substring(serviceInterface.lastIndexOf(".") + 1));
        }

        gatewayProxyBuilder.addConstructorArgValue(serviceInterface);

        AbstractBeanDefinition beanDefinition = gatewayProxyBuilder.getBeanDefinition();
        beanDefinition.addMetadataAttribute(new BeanMetadataAttribute(IntegrationConfigUtils.FACTORY_BEAN_OBJECT_TYPE,
                serviceInterface));

        return new BeanDefinitionHolder(beanDefinition, id);
    }


    /**
     * 获取该批注所有的变量
     */
    private List<MultiValueMap<String, Object>> captureMetaAnnotationValues(AnnotationMetadata importingClassMetadata) {
        Set<String> directAnnotations = importingClassMetadata.getAnnotationTypes();
        List<MultiValueMap<String, Object>> valuesHierarchy = new ArrayList<>();
        // Need to grab the values now; see SPR-11710
        for (String ann : directAnnotations) {
            Set<String> chain = importingClassMetadata.getMetaAnnotationTypes(ann);
            if (chain.contains(GMessage.class.getName())) {
                for (String meta : chain) {
                    valuesHierarchy.add(importingClassMetadata.getAllAnnotationAttributes(meta));
                }
            }
        }
        return valuesHierarchy;
    }


    /**
     * 防空措施
     */
    private void replaceEmptyOverrides(List<MultiValueMap<String, Object>> valuesHierarchy,
                                       Map<String, Object> annotationAttributes) {
        for (Map.Entry<String, Object> entry : annotationAttributes.entrySet()) {
            Object value = entry.getValue();
            if (!MessagingAnnotationUtils.hasValue(value)) {
                // see if we overrode a value that was higher in the annotation chain
                for (MultiValueMap<String, Object> metaAttributesMap : valuesHierarchy) {
                    Object newValue = metaAttributesMap.getFirst(entry.getKey());
                    if (MessagingAnnotationUtils.hasValue(newValue)) {
                        annotationAttributes.put(entry.getKey(), newValue);
                        break;
                    }
                }
            }
        }
    }
}
